iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0

原型模式通過讓物件提供複製方法,讓使用者能夠輕鬆複製物件。

生活案例

假設你是世界名畫「蒙娜麗莎的微笑」的收藏家。你經常收到美術館的來信,邀請展出這幅畫作。由於這幅畫極為珍貴,你不希望將它借出,但是你又無法拒絕那些誠摯的請求。於是,你想出了一個辦法,使用最先進的 3D 列印技術複製這幅畫,再將複製品借給美術館展覽。如此一來,不僅確保了畫作的安全,也實現了美術館的願望。雖然現實生活中沒有這麼便利的事,但在程式設計中,你可以透過原型模式來輕鬆複製物件。

舉個例子

假設我們有一個繪圖應用程式,可以繪製線條、圓形和矩形等幾何圖形。當使用者建立這些圖形後,他們可能會需要快速複製某些圖形。我們可以透過原型模式來實現圖形的複製功能。每一個圖形物件都可以有一個內建的複製方法,使用者只需選取圖形,即可輕鬆建立相同的圖形。

定義圖形原型,其中的抽象方法 clone 要求每個具體圖形實現自訂的複製功能。

abstract class Shape {
  public x: number;
  public y: number;
  public color: string;

  constructor(options: ShapeOptions) {
    this.x = options.x;
    this.y = options.y;
    this.color = options.color || "black";
  }

  abstract clone(): Shape;

  abstract toString(): string;
}

定義線條類別,使用者可以透過方法 clone 快速複製一個線條實體。

class Line extends Shape {
  public length: number;

  constructor(options: LineOptions) {
    super(options);
    this.length = options.length;
  }

  clone() {
    return new Line(this);
  }

  toString() {
    return `Line of length ${this.length}, starting at (${this.x}, ${this.y}), color: ${this.color}`;
  }
}

接下來,我們來設計畫布類別。畫布物件將使用者建立的所有圖形記錄在一個陣列中。我們可以在畫布上添加各種圖形,再利用方法 describe 印出所有圖形資訊。

class Canvas {
  private shapes: Shape[];

  constructor() {
    this.shapes = [];
  }

  addShape(shape: Shape) {
    this.shapes.push(shape);
  }

  describe() {
    console.log("Describing all shapes on the canvas:");
    for (const shape of this.shapes) {
      console.log(shape.toString());
    }
  }
}

測試時間。

class CanvasTestDrive {
  static main() {
    const canvas = new Canvas();

    const line = new Line({ x: 10, y: 10, length: 20 });
    const circle = new Circle({ x: 5, y: 5, radius: 10 });
    const rectangle = new Rectangle({ x: 15, y: 15, width: 30, height: 10 });

    const circleClone = circle.clone();
    const rectangleClone = rectangle.clone();

    canvas.addShape(line);
    canvas.addShape(circle);
    canvas.addShape(rectangle);
    canvas.addShape(circleClone);
    canvas.addShape(rectangleClone);

    canvas.describe();
  }
}

CanvasTestDrive.main();

輸出結果。

Describing all shapes on the canvas:
Line of length 20, starting at (10, 10), color: black
Circle with radius 10, centered at (5, 5), color: black
Rectangle of width 30 and height 10, positioned at (15, 15), color: black
Circle with radius 10, centered at (5, 5), color: black
Rectangle of width 30 and height 10, positioned at (15, 15), color: black

定義

Prototype Pattern

  • 原型(Prototype): 定義複製方法的介面
  • 具體類別(ConcretePrototype): 實作複製方法的類別

原型模式通過定義複製方法讓使用者快速複製一個物件。使用者只需透過複製方法複製物件,而不需依賴物件類別和建構邏輯,這讓物件複製變得非常容易。由於複製方法來自於物件本身,使用者可以連同物件的私有屬性一起複製。此外,原型模式使用建構式建立物件,因此複製出來的物件也保有所有類別方法。

當一個複雜的物件需要頻繁的被複製時,原型模式能夠有效簡化建構邏輯,提升程式的維護性。同時,透過共享資料,原型模式還能夠節省資源並提高效能。

總結

  • 允許程式複製物件但不依賴於物件的具體類別
  • 可以同時複製物件的公開和私有成員並保留類別方法
  • 簡化物件的複製流程,客戶端可以直接複製物件,而不需要重新撰寫初始化邏輯
  • 面對需要靈活且高效的操作物件的情境時,原型模式可以起到很好的作用

完整範例

https://github.com/chengen0612/design-patterns-typescript/blob/main/patterns/creational/prototype.ts


上一篇
Day 13 - Adapter 轉接器
下一篇
Day 15 - Builder 建造者
系列文
前端也想學設計模式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言